package com.kamistoat.meimeistore.commonredis;

import com.kamistoat.meimeistore.commonredis.configure.RedissonConfig;
import com.kamistoat.meimeistore.commonredis.configure.properties.RedissonProperties;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import java.io.IOException;

/**
 * meimeistore-manage-backstage-common-redis模块的AutoConfiguration类，用于将本模块中的Bean传递到依赖meimeistore-manage-backstage-common-redis的其他模块中。
 * 在SpringBoot2中需要在spring.factories中指定该类。
 *
 * 使用@Configuration注解标注该类。
 *
 * 使用@ComponentScan注解是为了扫描本模块中直接使用@Component/@Service等注解标注的类。如果不加该注解，那么只有在当前类中使用@Bean方法创建的Bean才能进行传递。
 * 原因很简单，@ComponentScan注解自动包含在@SpringBootApplication注解中，但是现在这个meimeistore-manage-backstage-common-redis模块并不是启动类，所以自然不包括@ComponentScan注解，要扫描必须手动添加。
 *
 * 使用了@EnableConfigurationProperties({RedissonProperties.class})后，将自定义配置也传递给依赖meimeistore-manage-backstage-common-redis的其他模块，
 * 这样其他模块也可以直接在yml文件中使用RedissonProperties中自定义的配置字段。
 */
@Configuration
@ComponentScan("com.kamistoat.meimeistore.commonredis")
@EnableConfigurationProperties({RedissonProperties.class})  // 在AutoConfiguration中配置第三方组件的自定义配置
public class CommonRedisAutoConfiguration implements InitializingBean {
    private final ApplicationContext applicationContext;
    private final RedissonProperties redissonProperties;

    /**
     * 该自动配置类的构造方法。同样不知道如何将 RedissonProperties 传递过来的。总之记住这么写就行了。
     * @param redissonProperties 依赖meimeistore-manage-backstage-common-redis的其他模块在yml中写的自定义redissonProperties
     * @param applicationContext 必须有的参数。
     */
    public CommonRedisAutoConfiguration(RedissonProperties redissonProperties, ApplicationContext applicationContext){
        this.redissonProperties = redissonProperties;
        this.applicationContext = applicationContext;
    }

    @Override
    public void afterPropertiesSet() throws Exception {
    }

    /**
     * 使用@Bean注解，根据 依赖meimeistore-manage-backstage-common-redis的其他模块在yml中写的自定义redissonProperties 来创建RedissonClient的Bean并传递回去。
     * @return
     * @throws IOException
     */
    @ConditionalOnMissingBean
    @Bean(destroyMethod = "shutdown")
    public RedissonClient redissonClient() throws IOException {
        // 获取Config
        Config redissonConfig = RedissonConfig.fixConfig(this.redissonProperties);
        // 创建RedissonClient
        RedissonClient redissonClient = Redisson.create(redissonConfig);
        return redissonClient;
    }
}
